package main

import (
	"context"
	"gdei_healthy_colly/config"
	"gdei_healthy_colly/log"
	"gdei_healthy_colly/msg"
	"gdei_healthy_colly/spider"
	"github.com/spf13/cobra"
	"go.uber.org/zap"
	"time"
)

const _version = "1.1.1"

var rootCMd = &cobra.Command{
	Use:   "ghc",
	Short: "广东第二师范学院健康定时打卡工具",
	Long:  "广东第二师范学院健康定时打卡工具，仅适用于健康定时打卡，不能用于商业活动",
}

func loadCmd() (err error) {
	userCmdInit()

	// 启动
	rootCMd.AddCommand(&cobra.Command{
		Use:   "run",
		Short: "启动定时器",
		Run: func(c *cobra.Command, args []string) {
			spider.Timer()
		},
	})

	// 强制启动
	rootCMd.AddCommand(&cobra.Command{
		Use:   "force",
		Short: "强制启动任务",
		Run: func(c *cobra.Command, args []string) {
			log.Logger.Info("[强制执行]", zap.Time("运行时间", time.Now()))
			for _, v := range spider.LoadAccounts() {
				func(ac spider.Account) {
					defer func() {
						if err := recover(); err != nil {
							log.Logger.Error("[强制执行]", zap.Any("崩溃", err))
						}
					}()
					// 错误重试，每次间隔15分钟
					var err error
					for rt := 0; rt < config.Cfg.Retry; rt++ {
						if err = spider.PostDailyForm(context.Background(), ac); err == nil {
							return
						}
						<-time.After(time.Duration(config.Cfg.RetryDelay) * time.Minute)
					}
					if err != nil {
						log.Logger.Info("[强制执行]",
							zap.String("ID", ac.GetId()),
							zap.String("username", ac.GetUsername()),
							zap.Error(err),
						)
					}
				}(v)
			}
		},
	})

	// 查看版本
	rootCMd.AddCommand(&cobra.Command{
		Use:   "version",
		Short: "查看版本",
		Run: func(c *cobra.Command, args []string) {
			log.Logger.Info("[系统]", zap.String("version", _version))
		},
	})

	// 登陆测试
	rootCMd.AddCommand(&cobra.Command{
		Use:   "login",
		Short: "登陆测试",
		Run: func(c *cobra.Command, args []string) {
			var pass, failed int
			for _, v := range spider.LoadAccounts() {
				if _err := spider.Login(context.Background(), v); _err != nil {
					failed++
					log.Logger.Error("[登陆测试]",
						zap.String("ID", v.GetId()),
						zap.String("Username", v.GetUsername()),
						zap.Error(_err),
					)
					continue
				}
				pass++
			}
			log.Logger.Info("[登陆测试]",
				zap.Int("总数", pass+failed),
				zap.Int("成功", pass),
				zap.Int("失败", failed),
			)
		},
	})

	// 配置测试
	rootCMd.AddCommand(&cobra.Command{
		Use:        "test",
		Short:      "配置测试",
		Deprecated: "请使用ghc users ls",
	})

	// 消息发送
	rootCMd.AddCommand(&cobra.Command{
		Use:   "msg",
		Short: "消息发送测试",
		Run: func(c *cobra.Command, args []string) {
			msg.ServerChanMsg(context.Background(),
				"[GHC消息]控制台消息测试", "消息发送测试"+time.Now().Format(time.RFC3339))
			<-time.After(time.Minute)
		},
	})

	// 账号管理
	rootCMd.AddCommand(userCmd)
	return
}

// 账号管理控制台
var userCmd = &cobra.Command{
	Use:   "user",
	Short: "账号管理",
}

// 初始化用户管理控制台
func userCmdInit() {
	userCmd.AddCommand(&cobra.Command{
		Use:   "ls",
		Short: "输出账号",
		Run: func(cmd *cobra.Command, args []string) {
			log.Logger.Info("[配置测试]",
				zap.Int("重试次数", config.Cfg.Retry),
				zap.Int("重试延迟(分钟)", config.Cfg.RetryDelay),
				zap.String("定时", config.Cfg.CommitTime))
			for _, v := range config.Cfg.Accounts {
				log.Logger.Info("[配置测试]",
					zap.String("ID", v.ID),
					zap.String("Username", v.Username),
				)
			}
		},
	})

	// 添加账号
	var username, password string
	addCmd := &cobra.Command{
		Use:   "add [学号]",
		Short: "添加账号",
		Args:  cobra.MinimumNArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			err := config.Cfg.AddAccount(args[0], config.WithUsername(username), config.WithPassword(password))
			if err != nil {
				log.Logger.Error("新增账号", zap.Error(err))
				return
			}
		},
	}
	addCmd.Flags().StringVarP(&username, "username", "u", "", "英文全名")
	addCmd.Flags().StringVarP(&password, "password", "p", "", "密码")
	_ = addCmd.MarkFlagRequired("username")
	_ = addCmd.MarkFlagRequired("password")
	userCmd.AddCommand(addCmd)

	// 修改账号
	editCmd := &cobra.Command{
		Use:   "edit [学号]",
		Short: "修改账号",
		Args:  cobra.MinimumNArgs(1),
		Run: func(cmd *cobra.Command, args []string) {
			err := config.Cfg.EditAccount(args[0], config.WithUsername(username), config.WithPassword(password))
			if err != nil {
				log.Logger.Error("修改账号", zap.Error(err))
				return
			}
		},
	}
	editCmd.Flags().StringVarP(&username, "username", "u", "", "英文全名")
	editCmd.Flags().StringVarP(&password, "password", "p", "", "密码")
	userCmd.AddCommand(editCmd)

	// 删除账号
	userCmd.AddCommand(&cobra.Command{
		Use:   "delete [学号]",
		Short: "删除账号",
		Run: func(cmd *cobra.Command, args []string) {
			err := config.Cfg.DeleteAccount(args[0])
			if err != nil {
				log.Logger.Error("删除账号", zap.Error(err))
			}
		},
	})
}
